import game.Game;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

import room.*;
import commands.*;
import game.*;

public class ActionCommand{
	private static final int WINDOW_WIDTH = 1000;

	private static final int WINDOW_HEIGHT = 300;

	private JFrame window;
	
	private Container c;
	
	private JPanel room = new JPanel();
	
	private JPanel roomHalf = new JPanel();
	
	private JPanel state = new JPanel();
	
	private JPanel stateHalf = new JPanel();
	
	private JPanel verb = new JPanel();
	
	private JPanel verbHalf = new JPanel();
	
	private JPanel say = new JPanel();
	
	private JPanel newFrame = new JPanel();
	
	private JPanel left = new JPanel();
	
	private JPanel oldFrame = new JPanel();
	
	private JPanel farEast = new JPanel();
	
	private JPanel buttonGrouping = new JPanel();
	
	private JPanel buttonsPanel = new JPanel();
	
	private JScrollPane roomPane;
	
	private JScrollPane statePane;
	
	private JScrollPane verbPane;
	
	private JScrollPane oldPane;
	
	private JSeparator leftBar = new JSeparator(SwingConstants.VERTICAL);
	
	private JSeparator rightBar = new JSeparator(SwingConstants.VERTICAL);
	
	private JLabel newEditor = new JLabel("Move To");
	
	private JList newActions = new JList(new String[] {"Move To","Change State","Invoke Another Room's Command","Output"});
	
	private JList oldActions;
	
	private DefaultListModel oldActionsModel = new DefaultListModel();
	
	private JButton newAdd = new JButton("<html><p align = \"center\">Create<br>Action");
	
	private JButton add = new JButton("Add");
	
	private JButton cancel = new JButton("Cancel");
	
	private JButton oldSubtract = new JButton("Remove");
	
	private JButton up = new JButton("/\\");
	
	private JButton down = new JButton("\\/");
	
	private JLabel roomTag;
	
	private JLabel stateTag;
	
	private JLabel verbTag;
	
	private JList roomList;
	
	public DefaultListModel roomListModel = new DefaultListModel();
	
	private JList stateList;
	
	private DefaultListModel stateListModel = new DefaultListModel();
	
	private JList verbList = new JList(new String[] {"Look","North","South","East","West"});
	
	private JTextArea sayEdit = new JTextArea();
	
	private ArrayList<Command> temp = new ArrayList<Command>();
	
	private Room myRoom;
	
	private RoomState myState;
	
	private String myVerb;
	
	public ActionCommand(Room targetRoom,RoomState targetState,String targetVerb){
		myRoom = targetRoom;
		myState = targetState;
		myVerb = targetVerb;		
		window = new JFrame(myRoom.getName() + " - " + myState.getDescription() + " - " + myVerb + " Action");
		window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
		window.setDefaultCloseOperation(window.DO_NOTHING_ON_CLOSE);
//		As we leave we are going to want to update the real
		window.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				forceExit();
			}
		});
		c = window.getContentPane();
		c.setLayout(new BorderLayout());
		left.setLayout(new BorderLayout());
		newEditor.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		newEditor.setBackground(Color.WHITE);
		newEditor.setOpaque(true);
		left.add("North",newEditor);
		newActions.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		newActions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		newActions.setSelectedIndex(0);
		newActions.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				newEditor.setText(newActions.getSelectedValue().toString());
			}
		});
		left.add("Center",newActions);
		newFrame.setLayout(new BoxLayout(newFrame,BoxLayout.LINE_AXIS));
		newFrame.add(left);
		newFrame.add(Box.createRigidArea(new Dimension(5, 0)));
		buttonsPanel.setLayout(new BoxLayout(buttonsPanel,BoxLayout.LINE_AXIS));
		c.add("Center",buttonsPanel);
		room.setLayout(new BoxLayout(room,BoxLayout.PAGE_AXIS));
		room.add(new JLabel("Room:"));
		roomHalf.setLayout(new BorderLayout());
		roomTag = new JLabel(myRoom.getName());
		roomTag.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		roomTag.setBackground(Color.WHITE);
		roomTag.setOpaque(true);
		roomHalf.add("North",roomTag);
		roomList = new JList(roomListModel);
		roomList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//		This listener will have to update roomList, and corespondingly stateList, as well as fixing temp if necissary.
		roomList.addListSelectionListener(new ListSelectionListener(){
//			We are using an isAdjusting catch in preparation for the action command window losing focus.
			public void valueChanged(ListSelectionEvent e){
				
//				We'll first set roomTag to reflect roomList's selection.				
				if(e.getValueIsAdjusting()){
					roomTag.setText(roomList.getSelectedValue().toString());

					int index;


//					We'll use index to find the currently selected room,
//					we do it here in case the buttonGrouping clause has need of the information.
					for(index = 0;index < TextAdventureGame.myGame.getRooms().size();index++){
						if(roomList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getName()))break;
					}

//					If state is showing we need to update that field to reflect the current room.
					if(state.isShowing()){
						stateListModel.clear();

//						This loop will step through the states repopulating the stateListModel.
						for(int counterbean = 0;counterbean < TextAdventureGame.myGame.getRooms().get(index).getStates().size();counterbean++){
							stateListModel.addElement(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean).getDescription());

//							If the current state is this rooms defualt state we'll set this to the selected item in the stateList.
							if(TextAdventureGame.myGame.getRooms().get(index).getCurrentState().equals(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean))){
								stateList.setSelectedIndex(stateListModel.size() - 1);
								stateTag.setText(TextAdventureGame.myGame.getRooms().get(index).getCurrentState().getDescription());
								
//								Rather than saving this Id we'll just go ahead and update the room and state of temp if that is nescesary.
								if(!buttonGrouping.isShowing()){
									((ChangeState)temp.get(oldActions.getSelectedIndex())).setRoom(TextAdventureGame.myGame.getRooms().get(index));
									((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean).getId());									
								}
							}
						}
//					Because we have already taken care of the ChangeState posibility we know that if buttonGrouping is showing we must be dealing with a Move event.
//					So we'll adjust temp acordingly.
					}else if(!buttonGrouping.isShowing()){				
						((Move)temp.get(oldActions.getSelectedIndex())).setRoom(TextAdventureGame.myGame.getRooms().get(index));
					}
				}
			}
		});
//		We'll need the KeyListener because the ListSelectionListener is buried inside a ValueIsAdjusting clause.
		roomList.addKeyListener(new KeyAdapter(){
//			Key events have to be handled here because the SelectionListener will dismiss them under the IsAdjusting clause.			
			public void keyReleased(KeyEvent ke) {
				roomTag.setText(roomList.getSelectedValue().toString());
				
				int index;


//				We'll use index to find the currently selected room,
//				we do it here in case the buttonGrouping clause has need of the information.
				for(index = 0;index < TextAdventureGame.myGame.getRooms().size();index++){
					if(roomList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getName()))break;
				}

//				If state is showing we need to update that field to reflect the current room.
				if(state.isShowing()){
					stateListModel.clear();

//					This loop will step through the states repopulating the stateListModel.
					for(int counterbean = 0;counterbean < TextAdventureGame.myGame.getRooms().get(index).getStates().size();counterbean++){
						stateListModel.addElement(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean).getDescription());

//						If the current state is this rooms defualt state we'll set this to the selected item in the stateList.
						if(TextAdventureGame.myGame.getRooms().get(index).getCurrentState().equals(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean))){
							stateList.setSelectedIndex(stateListModel.size() - 1);
							stateTag.setText(TextAdventureGame.myGame.getRooms().get(index).getCurrentState().getDescription());
							
//							Rather than saving this Id we'll just go ahead and update the room and state of temp if that is nescesary.
							if(!buttonGrouping.isShowing()){
								((ChangeState)temp.get(oldActions.getSelectedIndex())).setRoom(TextAdventureGame.myGame.getRooms().get(index));
								((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(TextAdventureGame.myGame.getRooms().get(index).getStates().get(counterbean).getId());									
							}
						}
					}
//				Because we have already taken care of the ChangeState posibility we know that if buttonGrouping is showing we must be dealing with a Move event.
//				So we'll adjust temp acordingly.
				}else if(!buttonGrouping.isShowing()){				
					((Move)temp.get(oldActions.getSelectedIndex())).setRoom(TextAdventureGame.myGame.getRooms().get(index));
				}			
			}
		});		
		roomPane = new JScrollPane(roomList);
		roomPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		roomHalf.add(roomPane);
		room.add(roomHalf);
		state.setLayout(new BoxLayout(state,BoxLayout.PAGE_AXIS));
		state.add(new JLabel("State:"));
		stateHalf.setLayout(new BorderLayout());
		stateTag = new JLabel(myState.getDescription());
		stateTag.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		stateTag.setBackground(Color.WHITE);
		stateTag.setOpaque(true);
		stateHalf.add("North",stateTag);
		stateList = new JList(stateListModel);
		stateList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//		Because the changes to the stateListModel will crash this function if the ValueIsAdjusting clause is not in place we must have it and the KeyListener function in the same role.		
		stateList.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
//				When we stop adjusting we'll update stateTag to reflect stateList's selected value.				
				if(e.getValueIsAdjusting()){
					stateTag.setText(stateList.getSelectedValue().toString());
					
//					If buttonGrouping isn't showing though that means that we're adjusting temp.
					if(!buttonGrouping.isShowing()){
						int index,stateCheck;

//						We'll use index to find the room that we're working with.
						for(index = 0;index < TextAdventureGame.myGame.getRooms().size();index++){
							if(roomList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getName()))break;
						}
											
//						We'll find the state with stateCheck just as we found the room with index.
						for(stateCheck = 0;stateCheck < TextAdventureGame.myGame.getRooms().get(index).getStates().size();stateCheck++){
							if(stateList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getDescription()))break;
						}						
						//Now that we have the state that we are seeking to modify we'll sdjust temp approperiately.
						((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getId());
					}
				}
			}
		});
		stateList.addKeyListener(new KeyAdapter(){
//			Key events have to be handled here because the SelectionListener will dismiss them under the IsAdjusting clause.			
			public void keyReleased(KeyEvent ke) {
				stateTag.setText(stateList.getSelectedValue().toString());
				
//				If buttonGrouping isn't showing though that means that we're adjusting temp.
				if(!buttonGrouping.isShowing()){
					int index,stateCheck;

//					We'll use index to find the room that we're working with.
					for(index = 0;index < TextAdventureGame.myGame.getRooms().size();index++){
						if(roomList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getName()))break;
					}
										
//					We'll find the state with stateCheck just as we found the room with index.
					for(stateCheck = 0;stateCheck < TextAdventureGame.myGame.getRooms().get(index).getStates().size();stateCheck++){
						if(stateList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getDescription()))break;
					}						
					//Now that we have the state that we are seeking to modify we'll sdjust temp approperiately.
					((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getId());
				}				
			}
		});
		statePane = new JScrollPane(stateList);
		statePane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		stateHalf.add(statePane);
		state.add(stateHalf);
		verb.setLayout(new BoxLayout(verb,BoxLayout.PAGE_AXIS));
		verb.add(new JLabel("Command:"));
		verbHalf.setLayout(new BorderLayout());
		verbTag = new JLabel(myVerb);
		verbTag.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		verbTag.setBackground(Color.WHITE);
		verbTag.setOpaque(true);
		verbHalf.add("North",verbTag);
		verbList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		verbList.setSelectedValue(myVerb, true);
		verbList.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				verbTag.setText(verbList.getSelectedValue().toString());
			}
		});
		verbPane = new JScrollPane(verbList);
		verbPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		verbHalf.add(verbPane);
		verb.add(verbHalf);
		say.setLayout(new BorderLayout());
		say.add("North",new JLabel("Enter Output Text:"));
		sayEdit.setWrapStyleWord(true);
		sayEdit.setLineWrap(true);		
		sayEdit.addFocusListener(new FocusListener(){
			public void focusGained(FocusEvent e) {	}
			public void focusLost(FocusEvent e) {

				if(!buttonGrouping.isShowing())((Say)temp.get(oldActions.getSelectedIndex())).setResponse(sayEdit.getText());
			}
		});
		say.add(new JScrollPane(sayEdit));
		buttonGrouping.setLayout(new BoxLayout(buttonGrouping,BoxLayout.PAGE_AXIS));
		add.setAlignmentX(Component.CENTER_ALIGNMENT);
//		The add JButton adds the action to temp and to the oldActions JList
		add.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent ae){
				
//				Firs we'll ensure that oldActions is activated.
				if(!oldActions.isEnabled()){
					oldActions.setEnabled(true);
				}

/*				Next we'll check whether the issued command was to Output.
				If it was we'll put the text into a Say Object and add that to temp.
				And adjust the oldActionsModel and oldActions selection acordingly as well.*/				
				if(say.isShowing()){
					temp.add(new Say(sayEdit.getText()));
					oldActionsModel.addElement("Output");
					oldActions.setSelectedIndex(oldActionsModel.size() - 1);
//				If the issued command was not Output, we'll decide what it was in this section. 				
				}else{
					int index;

//					Since all non-Output commands use a Room, we'll find the selected room.
					for(index = 0;index < TextAdventureGame.myGame.getRooms().size();index++){
						if(roomList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getName()))break;
					}
					
					if(state.isShowing()){
						int stateCheck;
						
//						In the cases of the Change State and Invoke Another Room's Command we'll need the state.
//						So we'll find the state with stateCheck just as we found the room with index.
						for(stateCheck = 0;stateCheck < TextAdventureGame.myGame.getRooms().get(index).getStates().size();stateCheck++){
							if(stateList.getSelectedValue().toString().equals(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getDescription()))break;
						}
						
//						If the verb was showing we are using the Invoke Another Room's Command command.				
						if(verb.isShowing()){
							int size;

/*							Sorry about the bad counterbean name.
  							But, size will step through all the objects in the state selected by stateCheck,
  							and at each ellement it will update oldActionsModel and temp.
  							Following the loop oldActions' selection will be updated.*/							
							for(size = 0;size < TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getVerbCommands(verbList.getSelectedValue().toString().toLowerCase()).size();size++){

								if(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getVerbCommands(verbList.getSelectedValue().toString().toLowerCase()).get(size).getClass() == Move.class){
									oldActionsModel.addElement("Move To");
								}else if(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getVerbCommands(verbList.getSelectedValue().toString().toLowerCase()).get(size).getClass() == ChangeState.class){
									oldActionsModel.addElement("Change State");
								}else if(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getVerbCommands(verbList.getSelectedValue().toString().toLowerCase()).get(size).getClass() == Say.class){
									oldActionsModel.addElement("Output");
								}
								temp.add(TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getVerbCommands(verbList.getSelectedValue().toString().toLowerCase()).get(size));
							}
							oldActions.setSelectedIndex(oldActions.getComponentCount() - 1);							
//						Otherwise we were changing the current state. So we'll add a ChangeState Object into temp,
//						update oldActionsModel, as well as the selection of oldActions.
						}else{
							temp.add(new ChangeState(TextAdventureGame.myGame.getRooms().get(index),TextAdventureGame.myGame.getRooms().get(index).getStates().get(stateCheck).getId()));
							oldActionsModel.addElement("Change State");
							oldActions.setSelectedIndex(oldActionsModel.size() - 1);							
						}
/*					If state was not showing that means that the command issued was Move To.
 					So, we'll create a Move Object and add it to temp.
 					Then we'll update oldActionsModel and the selection of oldActions.*/					
					}else{						
							temp.add(new Move(TextAdventureGame.myGame,TextAdventureGame.myGame.getRooms().get(index)));
							oldActionsModel.addElement("Move To");
							oldActions.setSelectedIndex(oldActionsModel.size() - 1);
					}
				}
//				Because oldActions' ListSelectionListener will disregard this selection change as a ValueIsAdjusting change,
//				we'll need to call fireSelectionListener from here.				
				fireSelectionListener();
			}
		});
		buttonGrouping.add(add);
		buttonGrouping.add(Box.createRigidArea(new Dimension(0, 5)));
		cancel.setAlignmentX(Component.CENTER_ALIGNMENT);
		cancel.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent ae){
				buttonsPanel.setVisible(false);
								
				if(oldActions.isEnabled()){
					fireSelectionListener();
					buttonsPanel.setVisible(true);
				}
				c.validate();
			}
		});
		buttonGrouping.add(cancel);	
		newAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				buttonsPanel.setVisible(true);
				buttonsPanel.removeAll();
				buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));	
				
				if(newEditor.getText().equals("Output")){
					buttonsPanel.add(say);
					sayEdit.setText("");
				}else{
					buttonsPanel.add(room);
					roomTag.setText(myRoom.getName());
					roomList.setSelectedValue(myRoom.getName(),true);
					
					if(newEditor.getText().equals("Change State") || newEditor.getText().equals("Invoke Another Room's Command")){
						buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
						buttonsPanel.add(state);
						stateListModel.clear();	
						
						for(int xcounterbean = 0;xcounterbean < TextAdventureGame.myGame.getRooms().size();xcounterbean++){

							if(TextAdventureGame.myGame.getRooms().get(xcounterbean).getName().equals(roomList.getSelectedValue().toString())){								
								
								for(int ycounterbean = 0;ycounterbean < TextAdventureGame.myGame.getRooms().get(xcounterbean).getStates().size();ycounterbean++){
									stateListModel.addElement(TextAdventureGame.myGame.getRooms().get(xcounterbean).getStates().get(ycounterbean).getDescription());
								}
								System.out.println("error");								
								stateList.setSelectedValue(TextAdventureGame.myGame.getRooms().get(xcounterbean).getCurrentState().getDescription(), true);
								stateTag.setText(TextAdventureGame.myGame.getRooms().get(xcounterbean).getCurrentState().getDescription());								
								break;
							}
						}
					}
					
					if(newEditor.getText().equals("Invoke Another Room's Command")){
						buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
						buttonsPanel.add(verb);
					}
				}
				buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
				buttonsPanel.add(buttonGrouping);
				buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
				buttonsPanel.repaint();
				c.validate();
			}
		});
		newFrame.add(newAdd);
		newFrame.add(Box.createRigidArea(new Dimension(5, 0)));
		leftBar.setSize(2, newActions.getHeight());
		leftBar.setForeground(Color.BLACK);
		newFrame.add(leftBar);
		c.add("West",newFrame);
		oldFrame.setLayout(new BoxLayout(oldFrame,BoxLayout.LINE_AXIS));
		rightBar.setSize(2, newActions.getHeight());
		rightBar.setForeground(Color.BLACK);
		oldFrame.add(rightBar);
		oldFrame.add(Box.createRigidArea(new Dimension(5, 0)));
		oldSubtract.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent ae){
				if(oldActions.isEnabled()){
					int remove = oldActions.getSelectedIndex();
					temp.remove(remove);
					oldActionsModel.removeElementAt(remove);
					
					if(temp.size() == 0){
						oldActions.setEnabled(false);
						buttonsPanel.setVisible(false);
					}else if(remove < oldActions.getComponentCount()){
						oldActions.setSelectedIndex(remove);
					}else{
						oldActions.setSelectedIndex(remove - 1);
					}
					fireSelectionListener();
				}
			}
		});
		oldFrame.add(oldSubtract);
		oldFrame.add(Box.createRigidArea(new Dimension(5, 0)));

//		If myState has more that just a Say Command attached to it we'll populate oldActions with its contents.
		if(myState.getVerbCommands(myVerb.toLowerCase()).size() > 1){
			int size;
			
//			In this loop we will sequentially add the contents of myState to oldActionsModel and temp.
//			After all the contents have been added we'll select the oldListModel's first element and fireSelectionListener on that element.
			for(size = 1;size < myState.getVerbCommands(myVerb.toLowerCase()).size();size++){
				
				if(myState.getVerbCommands(myVerb.toLowerCase()).get(size).getClass() == Move.class){
					oldActionsModel.addElement("Move To");
				}else if(myState.getVerbCommands(myVerb.toLowerCase()).get(size).getClass() == ChangeState.class){
					oldActionsModel.addElement("Change State");
				}else if(myState.getVerbCommands(myVerb.toLowerCase()).get(size).getClass() == Say.class){
					oldActionsModel.addElement("Output");
				}
				temp.add(myState.getVerbCommands(myVerb.toLowerCase()).get(size));
			}
			oldActions = new JList(oldActionsModel);
			oldActions.setSelectedIndex(0);
			fireSelectionListener();
//		If there are 1 or fewer elements in myState's commands,
//		we'll just set oldActions to represent an empty list and disable it.
		}else{			
			
//			If there is no initial say command in myStates command list,
//			we'll add it for consistancy's sake when we exit this window.
			if(myState.getVerbCommands(myVerb.toLowerCase()).size() == 0)myState.addVerb(myVerb.toLowerCase()).addFirst(new Say(""));
			oldActions = new JList(oldActionsModel);
			oldActions.setEnabled(false);
		}
		oldActions.addMouseListener(new MouseListener(){
			public void mouseClicked(MouseEvent e) {}
			public void mousePressed(MouseEvent e) {
				fireSelectionListener();
			}
			public void mouseReleased(MouseEvent e) {}
			public void mouseEntered(MouseEvent e) {
				if(say.isShowing() && !buttonGrouping.isShowing())((Say)temp.get(oldActions.getSelectedIndex())).setResponse(sayEdit.getText());
			}
			public void mouseExited(MouseEvent e) {}
		});
		oldActions.addListSelectionListener(new ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e){
				if(e.getValueIsAdjusting())fireSelectionListener();
			}
		});
		oldActions.addKeyListener(new KeyAdapter(){
			public void keyReleased(KeyEvent ke) {
				fireSelectionListener();
			}
		});
		oldPane = new JScrollPane(oldActions);
		oldPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		window.setVisible(true);
		oldPane.setPreferredSize(left.getSize());
		oldFrame.add(oldPane);
		oldFrame.add(Box.createRigidArea(new Dimension(5, 0)));
		farEast.setLayout(new BoxLayout(farEast,BoxLayout.PAGE_AXIS));
		up.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent ae){
				int select = oldActions.getSelectedIndex();
				Command hold = temp.get(select);
				
				
				if(select > 0){
					String holder = oldActionsModel.get(select).toString();
					oldActionsModel.set(select, oldActionsModel.get(select - 1));
					oldActionsModel.set(select - 1, holder);
					oldActions.setSelectedIndex(select - 1);
					temp.set(select, temp.get(select - 1));
					temp.set(select - 1, hold);
				}
			}
		});
		farEast.add(up);
		farEast.add(Box.createRigidArea(new Dimension(0, 5)));
		down.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent ae){
				int select = oldActions.getSelectedIndex();
				Command hold = temp.get(select);
				

				if(select < oldActions.getComponentCount()){
					String holder = oldActionsModel.get(select).toString();
					oldActionsModel.set(select, oldActionsModel.get(select + 1));
					oldActionsModel.set(select + 1, holder);
					oldActions.setSelectedIndex(select + 1);
					temp.set(select, temp.get(select + 1));
					temp.set(select + 1, hold);
				}
			}
		});
		farEast.add(down);
		oldFrame.add(farEast);
		c.add("East",oldFrame);
		window.addWindowFocusListener(new WindowFocusListener(){
			public void windowLostFocus(WindowEvent e) {}
			public void windowGainedFocus(WindowEvent e) {
				myRoom = TextAdventureGame.myGame.getRoom(myRoom.getId());
				myState = myRoom.getRoomState(myState.getId());
				
				if(myRoom == null || myState == null){
					window.dispose();
					return;
				}
				String roomholder;

				if(!roomListModel.isEmpty()){
					roomholder = roomList.getSelectedValue().toString();
				}else{
					roomholder = myRoom.getName();
				}				
				roomListModel.clear();

				for(int xcounterbean = 0;xcounterbean < TextAdventureGame.myGame.getRooms().size();xcounterbean++){
					roomListModel.addElement(TextAdventureGame.myGame.getRooms().get(xcounterbean).getName());

					if(TextAdventureGame.myGame.getRooms().get(xcounterbean).getName().equals(roomholder)){
						roomList.setSelectedValue(roomholder, true);
						roomTag.setText(roomholder);
						
						if(statePane.isShowing()){
							String stateholder;

							if(!stateListModel.isEmpty()){
								stateholder = stateList.getSelectedValue().toString();
							}else{
								stateholder = TextAdventureGame.myGame.getRooms().get(xcounterbean).getCurrentState().getDescription();
								
								if(!buttonGrouping.isShowing()){
									((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(TextAdventureGame.myGame.getRooms().get(xcounterbean).getCurrentState().getId());
								}
							}
							stateListModel.clear();

							for(int ycounterbean = 0;ycounterbean < TextAdventureGame.myGame.getRooms().get(xcounterbean).getStates().size();ycounterbean++){
								stateListModel.addElement(TextAdventureGame.myGame.getRooms().get(xcounterbean).getStates().get(ycounterbean).getDescription());

								if(TextAdventureGame.myGame.getRooms().get(xcounterbean).getStates().get(ycounterbean).getDescription().toString().equals(stateholder)){
									stateList.setSelectedValue(stateholder, true);
									stateTag.setText(stateholder);
								}
							}

							if(!stateList.getSelectedValue().toString().equals(stateholder)){
								window.dispose();
								return;
							}
						}
					}
				}

				if(!roomList.getSelectedValue().toString().equals(roomholder)){

					if(!roomListModel.contains(myRoom.getName())){
						window.dispose();
						return;
					}
					roomList.setSelectedValue(myRoom.getName(), true);
					roomTag.setText(myRoom.getName());
					
					if(statePane.isShowing()){
						String stateholder = myState.getDescription();

						if(!buttonGrouping.isShowing())((ChangeState)temp.get(oldActions.getSelectedIndex())).setStateID(myState.getId());
						stateListModel.clear();

						for(int ycounterbean = 0;ycounterbean < myRoom.getStates().size();ycounterbean++){
							stateListModel.addElement(myRoom.getStates().get(ycounterbean).getDescription());

							if(myRoom.getStates().get(ycounterbean).getDescription().toString().equals(stateholder)){
								stateList.setSelectedValue(stateholder, true);
								stateTag.setText(stateholder);
							}
						}

						if(!stateList.getSelectedValue().toString().equals(stateholder)){
							window.dispose();
							return;
						}
					}else{
						((Move)temp.get(oldActions.getSelectedIndex())).setRoom(myRoom);
					}
				}

				if(!oldActionsModel.isEmpty()){
					int actionsholder = oldActions.getSelectedIndex();

					for(int counterbean = temp.size() - 1;counterbean > -1;counterbean--){

						if(oldActionsModel.get(counterbean).toString().equals("Move To")){

							if(!roomListModel.contains(((Move)temp.get(counterbean)).getRoom().getName())){
								temp.remove(counterbean);
								oldActionsModel.removeElementAt(counterbean);

								if(oldActionsModel.isEmpty()){
									oldActions.setEnabled(false);
									buttonsPanel.setVisible(false);
								}

								if(actionsholder == counterbean){

									if(actionsholder < oldActions.getComponentCount()){
										oldActions.setSelectedIndex(actionsholder);
									}else{
										oldActions.setSelectedIndex(actionsholder - 1);
									}								
								}
							}
						}else if(oldActionsModel.get(counterbean).toString().equals("Change State")){

							if(!roomListModel.contains(((ChangeState)temp.get(counterbean)).getRoom().getName()) || ((ChangeState)temp.get(counterbean)).getRoom().getRoomState(((ChangeState)temp.get(counterbean)).getStateID()) == null){
								temp.remove(counterbean);
								oldActionsModel.removeElementAt(counterbean);

								if(oldActionsModel.isEmpty()){
									oldActions.setEnabled(false);
									buttonsPanel.setVisible(false);
								}

								if(actionsholder == counterbean){

									if(actionsholder < oldActions.getComponentCount()){
										oldActions.setSelectedIndex(actionsholder);
									}else{
										oldActions.setSelectedIndex(actionsholder - 1);
									}								
								}
							}							
						}
					}
					fireSelectionListener();					
				}
			}
		});		
	}
//	This method is used internally to redo the buttonsPanel's contents to reflect oldActions' current selection.	
	private void fireSelectionListener(){
//		We'll start by resetting buttonsPanel's contents except for the leading separator.
		buttonsPanel.removeAll();
		buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));				

//		First a check is made if the selection is Output. If it is buttonsPanel will reflect the Output command.
//		And sayEdit's text will reflect temp the coresponding temp's Say.
		if(oldActions.getSelectedValue().toString().equals("Output")){
			buttonsPanel.add(say);
			sayEdit.setText(temp.get(oldActions.getSelectedIndex()).run());
//		If this is not the case we know that we will be adding the room panel.		
		}else{
			buttonsPanel.add(room); 
			
			if(oldActions.getSelectedValue().toString().equals("Change State")){
				buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
				buttonsPanel.add(state);
				roomList.setSelectedValue(((ChangeState)temp.get(oldActions.getSelectedIndex())).getRoom().getName(), true);
				stateList.setSelectedValue(((ChangeState)temp.get(oldActions.getSelectedIndex())).getRoom().getRoomState(((ChangeState)temp.get(oldActions.getSelectedIndex())).getStateID()).getDescription(),true);
			}else{
				roomList.setSelectedValue(((Move)temp.get(oldActions.getSelectedIndex())).getRoom().getName(), true);
			}
		}
		buttonsPanel.add(Box.createRigidArea(new Dimension(5, 0)));
		buttonsPanel.repaint();
		c.validate();
	}
//	This function has been made public so that the window can be forced to close externally.
	public void forceExit(){
		int counterbean;
		
//		First I'll remove all of the command, but the first one from the state that I am modifying.
		for(counterbean = myState.getVerbCommands(myVerb.toLowerCase()).size() - 1;counterbean > 0;counterbean--){
			myState.getVerbCommands(myVerb.toLowerCase()).removeLast();
		}
		
//		Next I'll replace these commands with the new list that the user has inputted, and then I'll exit.
		for(counterbean = 0;counterbean < temp.size();counterbean++){
			myState.getVerbCommands(myVerb.toLowerCase()).add(temp.get(counterbean));
		}
		window.dispose();
	}
//	To allow other windows to determine the room I am editing, I'm going to have a getter for myRoom.
	public Room getRoom(){
		return myRoom;
	}
//	To allow other windows to determine the state I am editing, I'm going to have a getter for myState.
	public RoomState getState(){
		return myState;
	}
//	To allow other windows to determine the verb I am editing, I'm going to have a getter for myVerb.
	public String getVerb(){
		return myVerb;
	}
//	To allow other windows to modify the name of the verb that I am edditing,
//	I'm going to have a setter for myVerb.
	public void setVerb(String myVerb){
		this.myVerb = myVerb;
	}
}

